package com.xyy.saas.payment.api.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xyy.saas.payment.adpater.impl.PinganAdapter;
import com.xyy.saas.payment.adpater.jd.common.JDConstants;
import com.xyy.saas.payment.adpater.jd.service.JDAdpaterService;
import com.xyy.saas.payment.adpater.jd.vo.JDCancelContractRequest;
import com.xyy.saas.payment.adpater.jd.vo.JDContractSignConfirmRequest;
import com.xyy.saas.payment.adpater.jd.vo.JDContractSignRequest;
import com.xyy.saas.payment.adpater.jd.vo.cardbin.CardBinRequest;
import com.xyy.saas.payment.adpater.jd.vo.sign.JDOneKeySignApplyRequest;
import com.xyy.saas.payment.adpater.jd.vo.sign.JDQueryOneKeySignBanksRequest;
import com.xyy.saas.payment.adpater.jd.vo.sign.JDQueryOneKeySignResultRequest;
import com.xyy.saas.payment.common.enums.PictureEnum;
import com.xyy.saas.payment.common.exception.PaymentException;
import com.xyy.saas.payment.cores.api.PaymentOpenAccountApi;
import com.xyy.saas.payment.cores.bo.AccountModifyBo;
import com.xyy.saas.payment.cores.bo.jd.*;
import com.xyy.saas.payment.cores.enums.BusinessOrderTypeEnum;
import com.xyy.saas.payment.cores.enums.JDPayContractStatusEnum;
import com.xyy.saas.payment.cores.enums.JDPayContractTypeEnum;
import com.xyy.saas.payment.cores.enums.ResultCodeEnum;
import com.xyy.saas.payment.cores.param.*;
import com.xyy.saas.payment.cores.vo.AccountUpdateVo;
import com.xyy.saas.payment.cores.vo.MerchantAccountVO;
import com.xyy.saas.payment.cores.vo.OpenAccountVO;
import com.xyy.saas.payment.cores.vo.ResultVO;
import com.xyy.saas.payment.cores.vo.jd.*;
import com.xyy.saas.payment.dao.model.ApplyBankcardModify;
import com.xyy.saas.payment.dao.model.BankCardBind;
import com.xyy.saas.payment.dao.model.BankCardBindLog;
import com.xyy.saas.payment.dao.model.ThirdUserInfo;
import com.xyy.saas.payment.merchant.core.dto.*;
import com.xyy.saas.payment.merchant.core.service.AccountModifyService;
import com.xyy.saas.payment.merchant.core.service.AccountService;
import com.xyy.saas.payment.merchant.core.service.ApplyBankcardService;
import com.xyy.saas.payment.merchant.core.service.UserInfoService2;
import com.xyy.saas.payment.merchant.core.vo.UserInfoVo;
import com.xyy.saas.payment.service.*;
import com.xyy.saas.payment.util.JSONUtils;
import com.xyy.saas.payment.util.LeafUtil;
import com.xyy.saas.payment.util.PojoConvertUtil;
import com.xyy.saas.payment.util.RedisUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import java.util.*;

@Service(version = "1.0.0")
@Slf4j
public class PaymentOpenAccountApiImpl implements PaymentOpenAccountApi {
    @Autowired
    private PinganAdapter pinganAdapter;
    @Autowired
    private AccountService accountService;
    @Autowired
    private PayAccountService payAccountService;
    @Resource
    private AccountModifyService accountModifyService;
    @Resource
    private ApplyBankcardService applyBankcardService;
    @Resource
    private UserInfoService2 userInfoService2;
    @Resource
    private ThirdUserInfoService thirdUserInfoService;
    @Resource
    private ApplyBankcardModifyService applyBankcardModifyService;
    @Autowired
    private JDAdpaterService jdAdpaterService;
    @Autowired
    private BankCardBindService bankCardBindService;
    @Autowired
    private BankCardBindLogService bankCardBindLogService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private LeafUtil leafUtil;
    @Override
    public void testKFEJZB6274(String param) {
        try {
            JSONObject jsonObject = JSONObject.parseObject(param);
            OrderAmountInfoDto orderBalanceQueryParam = OrderAmountInfoDto.builder().
                    businessIdType(jsonObject.getString("businessOrderType")).
                    accountId(jsonObject.getString("accountId")).
                    payNo(jsonObject.getString("businessOrderNo")).
                    build();
            pinganAdapter.orderBalanceQuery(orderBalanceQueryParam);
        } catch (Exception e) {
            log.error("testKFEJZB6274",e);
        }
    }
    /**
     * 更新平安商户信息
     */
    @SneakyThrows
    @Override
    public void updateAccount(AccountUpdateVo accountUpdateVo) {
        try {
            log.info("更新商户信息:{}", JSON.toJSONString(accountUpdateVo));
            // 1、参数校验
            if (StringUtils.isBlank(accountUpdateVo.getAccountId())) {
                throw new PaymentException(ResultCodeEnum.PARAM_ERROR);
            }

            // 2、数据校验
            UserInfoVo userInfoVo = userInfoService2.queryUserInfo(accountUpdateVo.getAccountId());
            if (userInfoVo == null) {
                throw new PaymentException(ResultCodeEnum.USER_NOT_FOUND);
            }
            ThirdUserInfo thirdUserInfo = thirdUserInfoService.getThirdUserInfoByUserId(accountUpdateVo.getAccountId());
            if (thirdUserInfo == null) {
                throw new PaymentException(ResultCodeEnum.USER_NOT_FOUND);
            }

            // 3、数据填充

            // 4、发起请求
            pinganAdapter.updateAccount(accountUpdateVo, thirdUserInfo);
        } catch (Exception e) {
            log.error("PaymentOpenAccountApiImpl#updateAccount error:param={},error={}", JSON.toJSONString(accountUpdateVo), e.getMessage(), e);
            throw new PaymentException(ResultCodeEnum.DEFAULT_ERROR, e.getMessage());
        }
    }

    @Override
    public ResultVO<OpenAccountVO> create(MerchantAccountVO merchantAccountVO, String sign) {
        log.info("PaymentOpenAccountApiImpl#create start create. merchantAccountVO:{}, sign:{}", JSONUtils.toJSON(merchantAccountVO), sign);

        AccountDto accountDto = new AccountDto();
        BeanUtils.copyProperties(merchantAccountVO, accountDto, "businessIdType", "accountChannel", "accountType", "customerType");
        accountDto.setBusinessIdType(merchantAccountVO.getBusinessIdType().getType());
        accountDto.setAccountChannel(merchantAccountVO.getAccountChannel().getChannel());
        accountDto.setAccountType(merchantAccountVO.getAccountType().getType());
        accountDto.setCustomerType(merchantAccountVO.getCustomerType().getType());
        accountDto.setResendCode(merchantAccountVO.getResendCode());

        try {
            ResultVO resultVO = accountService.createAccount(accountDto, sign);
            log.info("PaymentOpenAccountApiImpl#create end create. merchantAccountVO:{}, resultVO:{}, sign:{}", JSONUtils.toJSON(merchantAccountVO), JSONUtils.toJSON(resultVO), sign);
            return resultVO;
        }
        catch(Exception e) {
            log.error("PaymentOpenAccountApiImpl#create create error. error:" + e.getMessage(), e);
            if(e instanceof PaymentException) {
                return ResultVO.createError(((PaymentException) e).getErrCode(), ((PaymentException) e).getErrMsg());
            } else {
                return ResultVO.createError("创建账户失败");
            }
        }
    }

    @Override
    public ResultVO<OpenAccountVO> queryByBusinessId(OpenAccountQueryParam queryParam, String sign) {
        if(null == queryParam || StringUtils.isBlank(queryParam.getBusinessId()) || StringUtils.isBlank(queryParam.getBusinessIdType())) {
            return ResultVO.createError(ResultCodeEnum.PARAM_ERROR);
        }

        String accountId = payAccountService.getAccountIdByBusiness(queryParam.getBusinessIdType(), queryParam.getBusinessId());
        OpenAccountVO result = new OpenAccountVO();
        result.setApplymentNo(accountId);
        return ResultVO.createSuccess(result);
    }

    /**
     * 修改企业账户信息
     */
    @Override
    public ResultVO<AccountModifyBo> modifyMerchant(MerchantAccountModifyParam param, String sign) {
        log.info("PaymentOpenAccountApiImpl#modifyMerchant start modify. MerchantAccountModifyParam:{}, sign:{}", JSONUtils.toJSON(param), sign);

        try {
            return accountModifyService.modifyMerchant(MerchantAccountModifyDto.transfer(param));
        }
        catch(Exception ex) {
            log.error("PaymentOpenAccountApiImpl#modifyMerchant modify error. message:" + ex.getMessage(), ex);

            if(ex instanceof PaymentException) {
                return ResultVO.createError(((PaymentException) ex).getErrCode(), ((PaymentException) ex).getErrMsg());
            }
            else {
                return ResultVO.createError("企业修改账户失败");
            }
        }
    }

    /**
     * 修改个人账户信息
     */
    @Override
    public ResultVO<AccountModifyBo> modifyPersonal(PersonalAccountModifyParam param, String sign) {
        log.info("PaymentOpenAccountApiImpl#modifyPersonal modify start. PersonalAccountModifyParam:{}, sign:{}", JSONUtils.toJSON(param), sign);

        try {
            return accountModifyService.modifyPersonal(PersonalAccountModifyDto.transfer(param));
        }
        catch(Exception ex) {
            log.error("PaymentOpenAccountApiImpl#modifyPersonal modify error. message:" + ex.getMessage(), ex);

            if(ex instanceof PaymentException) {
                return ResultVO.createError(((PaymentException) ex).getErrCode(), ((PaymentException) ex).getErrMsg());
            }
            else {
                return ResultVO.createError("个人修改账户失败，"+ ex.getMessage());
            }
        }
    }

    /**
     * 查询企业账户信息
     */
    @Override
    public ResultVO<MerchantAccountModifyParam> queryModifyMerchant(QueryAccountModifyParam param, String sign) {
        log.info("PaymentOpenAccountApiImpl#queryModifyMerchant start. QueryAccountModifyParam:{}, sign:{}", JSONUtils.toJSON(param), sign);

        try {
            return ResultVO.createSuccess(MerchantAccountModifyDto.transfer(accountModifyService.queryModifyMerchant(param)));
        }
        catch(Exception ex) {
            log.error("PaymentOpenAccountApiImpl#queryModifyMerchant error. message:" + ex.getMessage(), ex);

            if(ex instanceof PaymentException) {
                return ResultVO.createError(((PaymentException) ex).getErrCode(), ((PaymentException) ex).getErrMsg());
            }
            else {
                return ResultVO.createError("查询企业账户修改信息失败，"+ ex.getMessage());
            }
        }
    }

    /**
     * 查询企业账户信息
     */
    @Override
    public ResultVO<List<MerchantAccountModifyParam>> queryModifyMerchantList(QueryAccountModifyParam param, String sign) {
        log.info("PaymentOpenAccountApiImpl#queryModifyMerchantList start. QueryAccountModifyParam:{}, sign:{}", JSONUtils.toJSON(param), sign);

        try {
            return ResultVO.createSuccess(MerchantAccountModifyDto.transferParam(accountModifyService.queryListModifyMerchant(param)));
        }
        catch(Exception ex) {
            log.error("PaymentOpenAccountApiImpl#queryModifyMerchantList error. message:" + ex.getMessage(), ex);

            if(ex instanceof PaymentException) {
                return ResultVO.createError(((PaymentException) ex).getErrCode(), ((PaymentException) ex).getErrMsg());
            }
            else {
                return ResultVO.createError("查询企业账户修改信息失败，"+ ex.getMessage());
            }
        }
    }

    /**
     * 打款认证
     */
    @Override
    public ResultVO paymentAuth(PaymentAuthParam param) {
        log.info("PaymentOpenAccountApiImpl#paymentAuth param:{}", JSONUtils.toJSON(param));

        try {
            // 0.copy参数
            PaymentAuthParam2 param2 = new PaymentAuthParam2();
            BeanUtils.copyProperties(param, param2);

            // 1.认证
            applyBankcardService.auth(param2);

            // 2.响应
            return ResultVO.createSuccess();
        }
        catch(Exception ex) {
            log.error("PaymentOpenAccountApiImpl#paymentAuth param=" + JSONUtils.toJSON(param), ex);

            if(ex instanceof PaymentException) {
                return ResultVO.createError(((PaymentException) ex).getErrCode(), ((PaymentException) ex).getErrMsg());
            }
            else {
                return ResultVO.createError(ResultCodeEnum.BANK_CARD_AUTH_FAIL);
            }
        }
    }

    /**
     * 查询在平安开户状态
     */
    @Override
    public ResultVO<AccountInfoVo> queryPingAnActStatus(AccountInfoParam param) {
        log.info("queryActStatus param:{}", JSONUtils.toJSON(param));

        try {
            // 1.参数校验
            if(param == null || param.getBusinessIdType() == null || StringUtils.isBlank(param.getBusinessId())) {
                throw new PaymentException(ResultCodeEnum.PARAM_ERROR);
            }
            AccountInfoVo accountInfoVo = AccountInfoVo.builder().status("0").build();
            // 2.账户校验
            String accountId = payAccountService.getAccountIdByBusiness(param.getBusinessIdType().getType(), param.getBusinessId());

            if(StringUtils.isBlank(accountId)) {
                accountInfoVo.setStatus("0");
                return ResultVO.createSuccess(accountInfoVo);
            }

            // 3.查询开户信息
            ThirdUserInfo thirdUserInfo = thirdUserInfoService.getThirdUserInfoByUserId(accountId);
            log.info("PaymentOpenAccountApiImpl#queryAccountInfo thirdUserInfo:{}", JSONUtils.toJSON(thirdUserInfo));
            if (thirdUserInfo != null && "pingan".equals(thirdUserInfo.getThirdType()) && StringUtils.isNotBlank(thirdUserInfo.getAccountNo())) {
                accountInfoVo.setStatus("1");
                return ResultVO.createSuccess(accountInfoVo);
            }
            return ResultVO.createSuccess(accountInfoVo);
        }
        catch(Exception ex) {
            log.error(ex.getMessage() + ", 查询开户信息异常，param=" + JSONUtils.toJSON(param), ex);

            if(ex instanceof PaymentException) {
                return ResultVO.createError(((PaymentException) ex).getErrCode(), ((PaymentException) ex).getErrMsg());
            }
            else {
                return ResultVO.createError(ResultCodeEnum.DEFAULT_ERROR.getCode(), "查询开户信息异常");
            }
        }
    }

    /**
     * 查询账户信息
     */
    @Override
    public ResultVO<AccountInfoVo> queryAccountInfo(AccountInfoParam param) {
        log.info("PaymentOpenAccountApiImpl#queryAccountInfo param:{}", JSONUtils.toJSON(param));

        try {
            // 1.参数校验
            if(param == null || param.getBusinessIdType() == null || StringUtils.isBlank(param.getBusinessId())) {
                throw new PaymentException(ResultCodeEnum.PARAM_ERROR);
            }

            // 2.账户校验
            String accountId = payAccountService.getAccountIdByBusiness(param.getBusinessIdType().getType(), param.getBusinessId());

            if(StringUtils.isBlank(accountId)) {
                AccountInfoVo data = AccountInfoVo.builder().status("0").build();
                return ResultVO.createSuccess(data);
            }

            // 3.查询开户信息
            UserInfoVo userInfoVo = userInfoService2.queryUserInfo(accountId);

            // 4.查询平安开户状态
            ApplyBankcardModify applyBankcardModify = applyBankcardModifyService.queryApplyInfoByAccountId(accountId, StringUtils.EMPTY);
            String status = "";
            if (applyBankcardModify == null) {
                ThirdUserInfo thirdUserInfo = thirdUserInfoService.getThirdUserInfoByUserId(accountId);
                log.info("PaymentOpenAccountApiImpl#queryAccountInfo thirdUserInfo:{}", JSONUtils.toJSON(thirdUserInfo));
                if (thirdUserInfo != null && "pingan".equals(thirdUserInfo.getThirdType()) && StringUtils.isBlank(thirdUserInfo.getAccountNo())) {
                    status="0";
                }
            } else {
                status = String.valueOf(applyBankcardModify.getStatus());
            }
            log.info("PaymentOpenAccountApiImpl#queryAccountInfo status:{}", status);

            // 4.响应
            AccountInfoVo data = AccountInfoVo.builder().
                    // 业务侧商户标识
                    businessId(param.getBusinessId()).
                    // 企业信息
                    enterpriseName(userInfoVo.getBasicInfo().getName()).
                    enterpriseRegistrationNo(userInfoVo.getBasicInfo().getIdentityInfo().getId()).
                    businessLicenseUrl(userInfoVo.getPicInfo().get(PictureEnum.BUSINESS_CERT_PIC.getCode())).
                    // 法人信息
                    corporationName(userInfoVo.getContactInfo().get(NumberUtils.INTEGER_ZERO).getContactName()).
                    corporationIdNo(userInfoVo.getContactInfo().get(NumberUtils.INTEGER_ZERO).getContactCertNo()).
                    corporationIdCardFrontUrl(userInfoVo.getPicInfo().get(PictureEnum.LEGAL_CERT_FRONT.getCode())).
                    corporationIdCardBackUrl(userInfoVo.getPicInfo().get(PictureEnum.LEGAL_CERT_BACK.getCode())).
                    corporationPhone(userInfoVo.getContactInfo().get(NumberUtils.INTEGER_ZERO).getContactCertMobile()).
                    // 银行卡信息
                    accountName(userInfoVo.getSettleInfo().getRecipient().getName()).
                    acct(userInfoVo.getSettleInfo().getRecipient().getAccount()).
                    bankName(userInfoVo.getSettleInfo().getRecipient().getOpenBank()).
                    branchBankCd(userInfoVo.getSettleInfo().getRecipient().getSubBankCode()).
                    branchBankName(userInfoVo.getSettleInfo().getRecipient().getSubBank()).
                    // 平台开户状态
                    status(status).
                    message(applyBankcardModify != null ? applyBankcardModify.getMessage() : StringUtils.EMPTY).
                    binded(applyBankcardModifyService.binded(accountId)).
                    build();
            return ResultVO.createSuccess(data);
        }
        catch(Exception ex) {
            log.error(ex.getMessage() + ", 查询开户信息异常，param=" + JSONUtils.toJSON(param), ex);

            if(ex instanceof PaymentException) {
                return ResultVO.createError(((PaymentException) ex).getErrCode(), ((PaymentException) ex).getErrMsg());
            }
            else {
                return ResultVO.createError(ResultCodeEnum.DEFAULT_ERROR.getCode(), "查询开户信息异常");
            }
        }
    }

    @Override
    public ResultVO mntMbrBindSameRealCustNameAcct(String thirdUserId,String sellerThirdUserId) {
        try {
            log.info("mntMbrBindSameRealCustNameAcct param:{} {}",thirdUserId,sellerThirdUserId);

            if (StringUtils.isEmpty(thirdUserId) || StringUtils.isEmpty(sellerThirdUserId)) {
                return ResultVO.createError(ResultCodeEnum.DEFAULT_ERROR.getCode(), "入参不能为空");
            }
            String accountId = payAccountService.getAccountIdByBusiness(BusinessOrderTypeEnum.EC.getType(), thirdUserId);
            String sellerAccountId = payAccountService.getAccountIdByBusiness(BusinessOrderTypeEnum.EC_POP.getType(), sellerThirdUserId);

            if (StringUtils.isEmpty(accountId) || StringUtils.isEmpty(sellerAccountId)) {
                log.warn("buyer/seller accountId is empty buyUserId:{} sellerUserId:{} buyAccountId:{} sellerAccountId:{}", thirdUserId, sellerAccountId, accountId, sellerAccountId);
                return ResultVO.createSuccess(null);
            }
            applyBankcardService.mntMbrBindSameRealCustNameAcct(accountId,sellerAccountId);
            return ResultVO.createSuccess(null);
        } catch (Exception e) {
            log.error("mntMbrBindSameRealCustNameAcct param:{} {}", thirdUserId, sellerThirdUserId, e);

            if (e instanceof PaymentException) {
                PaymentException pe = (PaymentException) e;
                if (Objects.equals("E10016", pe.getErrCode())) {
                    // 同名户绑定关系已存在 无需维护
                    return ResultVO.createSuccess(null);
                }

                String errMsg = pe.getErrMsg();
                if (StringUtils.isNotBlank(errMsg)) {
                    return ResultVO.createError(ResultCodeEnum.DEFAULT_ERROR.getCode(), errMsg);
                }
            }
            return ResultVO.createError(ResultCodeEnum.DEFAULT_ERROR.getCode(), "查询开户信息异常");
        }
    }



    /**
     * 京东一键签约 - 查询一键签约列表
     */
    @Override
    public ResultVO<List<JDBankDto>> queryOneKeySignBanks(JDQueryOneKeySignBanksVo jdQueryOneKeySignBanksVo) {
        String logPrefix = "PaymentOpenAccountApiImpl#queryOneKeySignBanks " + jdQueryOneKeySignBanksVo.getMerchantNo();
        log.info("{} start. JDQueryOneKeySignBanksVo:{}", logPrefix, JSONUtils.toJSON(jdQueryOneKeySignBanksVo));
        try {
            // 1、参数校验
            PojoConvertUtil.checkBlank(jdQueryOneKeySignBanksVo, Arrays.asList("merchantNo"));
            // 2、拼装请求数据
            JDQueryOneKeySignBanksRequest jdQueryOneKeySignBanksRequest = JDQueryOneKeySignBanksRequest.builder().userId(jdQueryOneKeySignBanksVo.getBindAccount()).phone(jdQueryOneKeySignBanksVo.getPhone()).merchantNo(jdQueryOneKeySignBanksVo.getMerchantNo()).build();
            // 3、调用接口查询结果
            JDQueryOneKeySignBanksDto jdQueryOneKeySignBanksDto = jdAdpaterService.queryOneKeySignBanks(logPrefix, jdQueryOneKeySignBanksRequest);
            return ResultVO.createSuccess(jdQueryOneKeySignBanksDto.getBankList());
        } catch (Exception ex) {
            log.error("{}_error param = {} , {}", logPrefix, JSONUtils.toJSON(jdQueryOneKeySignBanksVo), ex);
            if(ex instanceof PaymentException) {
                PaymentException paymentException = (PaymentException) ex;
                return ResultVO.createError(paymentException.getErrCode(), paymentException.getErrMsg());
            }
            return ResultVO.createError(ResultCodeEnum.DEFAULT_ERROR);
        }
    }

    /**
     * 京东一键签约 - 一键签约申请
     */
    @Override
    public ResultVO<JDOneKeySignApplyDto> oneKeySignApply(JDOneKeySignApplyVo jdOneKeySignApplyVo) {
        String logPrefix = "PaymentOpenAccountApiImpl#oneKeySignApply " + jdOneKeySignApplyVo.getBusinessReqNo();
        log.info("{} start. JDOneKeySignApplyVo:{}", logPrefix, JSONUtils.toJSON(jdOneKeySignApplyVo));
        boolean lockSuc = false;
        String lockKey = RedisUtil.JD_PAY_PREFIX + "oneKeySignApply_" + jdOneKeySignApplyVo.getMerchantNo() + "_" + jdOneKeySignApplyVo.getBindAccount();
        try {
            // 1.参数校验
            PojoConvertUtil.checkBlank(jdOneKeySignApplyVo, Arrays.asList("businessReqNo", "bindAccount", "bindUser", "terminalType", "contractStyle", "businessType", "merchantNo", "bankCode", "bankName", "cardType", "idName", "idNo", "signPageCallBackUrl"));
            if (!redisUtil.tryLock(lockKey)) {
                throw new PaymentException(ResultCodeEnum.JD_BUSY_ONE_KEY_APPLY);
            }
            lockSuc = true;
            // 2、拼装请求数据
            JDOneKeySignApplyRequest jdOneKeySignApplyRequest = new JDOneKeySignApplyRequest();
            BeanUtils.copyProperties(jdOneKeySignApplyVo, jdOneKeySignApplyRequest);
            // 3、调用接口
            JDOneKeySignApplyDto jdOneKeySignApplyDto = jdAdpaterService.oneKeySignApply(logPrefix, jdOneKeySignApplyRequest);
            // 4、填充信息
            jdOneKeySignApplyDto.setRequestNo(jdOneKeySignApplyRequest.getRequestNo());
            // 5、组装数据并保存请求流水
            Map<String, String> extent = (null == jdOneKeySignApplyVo.getExtent() ? new HashMap<>() : jdOneKeySignApplyVo.getExtent());
            extent.put("terminalType", jdOneKeySignApplyVo.getTerminalType());
            extent.put("contractStyle", jdOneKeySignApplyVo.getContractStyle());
            extent.put("idNo", jdOneKeySignApplyVo.getIdNo());
            BankCardBind bankCardBind = BankCardBind.builder()
                    .channel(JDConstants.CHANNEL_CONTRACT).merchantNo(jdOneKeySignApplyVo.getMerchantNo())
                    .businessType(jdOneKeySignApplyVo.getBusinessType()).reqNo(jdOneKeySignApplyRequest.getRequestNo())
                    .contractReqNo(jdOneKeySignApplyRequest.getRequestNo()).bindAccount(jdOneKeySignApplyVo.getBindAccount())
                    .bindUser(jdOneKeySignApplyVo.getBindUser()).cardType(jdOneKeySignApplyVo.getCardType())
                    .bankCode(jdOneKeySignApplyVo.getBankCode()).bankName(jdOneKeySignApplyVo.getBankName())
                    .idName(jdOneKeySignApplyVo.getIdName()).idType(jdOneKeySignApplyRequest.getIdType())
                    .idNo(jdOneKeySignApplyVo.getIdNo()).bankPhone(jdOneKeySignApplyVo.getPhone())
                    .extent(JSONObject.toJSONString(extent)).contractStatus(JDPayContractStatusEnum.PROC.getCode())
                    .contractType(JDPayContractTypeEnum.ONEKEYSIGN.getCode()).contractNo("").cardNo("")
                    .resultCode(jdOneKeySignApplyDto.getCode()).resultDesc(jdOneKeySignApplyDto.getMessage())
                    .build();
            bankCardBindService.insert(bankCardBind);
            return ResultVO.createSuccess(jdOneKeySignApplyDto);
        } catch (Exception ex) {
            log.error("{}_error param = {} , {}", logPrefix, JSONUtils.toJSON(jdOneKeySignApplyVo), ex);
            if(ex instanceof PaymentException) {
                PaymentException paymentException = (PaymentException) ex;
                return ResultVO.createError(paymentException.getErrCode(), paymentException.getErrMsg());
            }
            return ResultVO.createError(ResultCodeEnum.DEFAULT_ERROR);
        } finally {
            if (lockSuc) {
                redisUtil.unLock(lockKey);
            }
        }
    }

    /**
     * 京东一键签约 - 签约结果查询
     */
    @Override
    public ResultVO<JDBankCardBindDto> queryOneKeySignResult(JDQueryOneKeySignResultVo jdQueryOneKeySignResultVo) {
        String logPrefix = "PaymentOpenAccountApiImpl#queryOneKeySignResult " + jdQueryOneKeySignResultVo.getBusinessReqNo() + "_" + jdQueryOneKeySignResultVo.getRequestNo();
        log.info("{} start. JDQueryOneKeySignResultVo:{}", logPrefix, JSONUtils.toJSON(jdQueryOneKeySignResultVo));
        boolean lockSuc = false;
        String lockKey = RedisUtil.JD_PAY_PREFIX + "queryOneKeySignResult_" + jdQueryOneKeySignResultVo.getRequestNo();
        try {
            // 1、参数校验
            PojoConvertUtil.checkBlank(jdQueryOneKeySignResultVo, Arrays.asList("businessReqNo", "merchantNo", "requestNo"));
            if (!redisUtil.tryLock(lockKey)) {
                throw new PaymentException(ResultCodeEnum.JD_BUSY_SIGN_RESULT);
            }
            lockSuc = true;
            // 2、从数据库查询签约结果，若不为签约中，则返回
            BankCardBind bankCardBind = bankCardBindService.queryByReqNo(jdQueryOneKeySignResultVo.getRequestNo());
            if (null == bankCardBind) {
                throw new PaymentException(ResultCodeEnum.JD_CONTRACT_NOTEXIST);
            }
            // 3、当数据库中记录为处理中时，是否调用三方接口进行数据同步，若不同步，则直接返回
            if (!jdQueryOneKeySignResultVo.isSync()) {
                return ResultVO.createSuccess(PojoConvertUtil.convertPojo(bankCardBind, JDBankCardBindDto::new));
            }
            if (JDPayContractStatusEnum.PROC.getCode() != bankCardBind.getContractStatus()) {
                return ResultVO.createSuccess(PojoConvertUtil.convertPojo(bankCardBind, JDBankCardBindDto::new));
            }
            // 4、数据库若为处理中，则调用查询接口查询，拼装请求数据
            JDQueryOneKeySignResultRequest jdQueryOneKeySignResultRequest = new JDQueryOneKeySignResultRequest();
            BeanUtils.copyProperties(jdQueryOneKeySignResultVo, jdQueryOneKeySignResultRequest);
            // 5、调用接口查询结果
            JDMerchantOneKeySignResultDto jdMerchantOneKeySignResultDto = jdAdpaterService.queryOneKeySignResult(logPrefix, jdQueryOneKeySignResultRequest);
            // 6、处理查询结果
            jdAdpaterService.dealOneKeySignResult(logPrefix, bankCardBind, jdMerchantOneKeySignResultDto);
            return ResultVO.createSuccess(PojoConvertUtil.convertPojo(bankCardBind, JDBankCardBindDto::new));
        } catch (Exception ex) {
            log.error("{}_error param = {} , {}", logPrefix, JSONUtils.toJSON(jdQueryOneKeySignResultVo), ex);
            if(ex instanceof PaymentException) {
                PaymentException paymentException = (PaymentException) ex;
                return ResultVO.createError(paymentException.getErrCode(), paymentException.getErrMsg());
            }
            return ResultVO.createError(ResultCodeEnum.DEFAULT_ERROR);
        } finally {
            if (lockSuc) {
                redisUtil.unLock(lockKey);
            }
        }
    }

    /**
     * 京东 - 渠道卡信息查询
     */
    @Override
    public ResultVO<JDCardBinDataDto> cardbin(JDCardBinRequestVo jdCardBinRequestVo) {
        String logPrefix = "PaymentOpenAccountApiImpl#cardbin " + jdCardBinRequestVo.getCardNo();
        log.info("{} start. JDCardBinRequestVo:{}", logPrefix, JSONUtils.toJSON(jdCardBinRequestVo));
        boolean lockSuc = false;
        String lockKey = RedisUtil.JD_PAY_PREFIX + "cardbin_" + jdCardBinRequestVo.getBindAccount() + "_" + jdCardBinRequestVo.getCardNo();
        try {
            // 1.参数校验
            PojoConvertUtil.checkBlank(jdCardBinRequestVo, Arrays.asList("merchantNo", "cardNo", "bindAccount"));
            if (!redisUtil.tryLock(lockKey)) {
                throw new PaymentException(ResultCodeEnum.JD_BUSY_CARD_BIN);
            }
            lockSuc = true;
            // 2、拼装请求数据
            CardBinRequest cardBinRequest = new CardBinRequest();
            BeanUtils.copyProperties(jdCardBinRequestVo, cardBinRequest);
            // 3、调用接口查询结果
            JDCardBinDataDto jdCardBinDataDto = jdAdpaterService.cardbin(logPrefix, cardBinRequest);
            if (jdCardBinDataDto.getCardType().contains("借记")) {
                jdCardBinDataDto.setCardType("DE");
            } else {
                jdCardBinDataDto.setCardType("CR");
            }
            if (null != jdCardBinRequestVo.getCheck() && jdCardBinRequestVo.getCheck()) {
                // 验证是否存在签约完成的记录 : merchantNo、bindAccount、bankCode、cardNo、ContractStatus
                BankCardBind cardBind = BankCardBind.builder().merchantNo(jdCardBinRequestVo.getMerchantNo()).bindAccount(jdCardBinRequestVo.getBindAccount()).bankCode(jdCardBinDataDto.getBankCode()).cardNo(jdCardBinRequestVo.getCardNo()).contractStatus(JDPayContractStatusEnum.SUCC.getCode()).build();
                if (bankCardBindService.count(cardBind) > 0) {
                    throw new PaymentException(ResultCodeEnum.JD_CONTRACT_SUCC);
                }
            }
            jdCardBinDataDto.setPaymentAgreementUrl(JDConstants.PAYMENT_AGREEMENT_URL);
            return ResultVO.createSuccess(jdCardBinDataDto);
        } catch (Exception ex) {
            log.error("{}_error param = {} , {}", logPrefix, JSONUtils.toJSON(jdCardBinRequestVo), ex);
            if(ex instanceof PaymentException) {
                PaymentException paymentException = (PaymentException) ex;
                return ResultVO.createError(paymentException.getErrCode(), paymentException.getErrMsg());
            }
            return ResultVO.createError(ResultCodeEnum.DEFAULT_ERROR);
        } finally {
            if (lockSuc) {
                redisUtil.unLock(lockKey);
            }
        }
    }

    /**
     * 京东 - 协议签约接口
     */
    @Override
    public ResultVO<JDContractSignDto> contractSign(JDContractSignVo jdContractSignVo) {
        String logPrefix = "PaymentOpenAccountApiImpl#contractSign " + jdContractSignVo.getBusinessReqNo();
        log.info("{} start. JDContractSignVo:{}", logPrefix, JSONUtils.toJSON(jdContractSignVo));
        boolean lockSuc = false;
        String lockKey = RedisUtil.JD_PAY_PREFIX + "contractSign_" + jdContractSignVo.getBindAccount() + "_" + jdContractSignVo.getCardNo();
        try {
            // 1.参数校验
            PojoConvertUtil.checkBlank(jdContractSignVo, Arrays.asList("businessReqNo", "bindAccount", "merchantNo", "bankCode", "bankName", "cardType", "cardNo", "idNo", "idName", "phone"));
            if (!redisUtil.tryLock(lockKey)) {
                throw new PaymentException(ResultCodeEnum.JD_BUSY_CONTRACT_SIGN);
            }
            lockSuc = true;
            // 2、验证是否存在签约完成的记录 : merchantNo、bindAccount、bankCode、cardNo、contractStatus
            BankCardBind cardBindSuc = BankCardBind.builder().merchantNo(jdContractSignVo.getMerchantNo()).bindAccount(jdContractSignVo.getBindAccount()).bankCode(jdContractSignVo.getBankCode()).cardNo(jdContractSignVo.getCardNo()).contractStatus(JDPayContractStatusEnum.SUCC.getCode()).build();
            if (bankCardBindService.count(cardBindSuc) > 0) {
                throw new PaymentException(ResultCodeEnum.JD_CONTRACT_SUCC);
            }
            // 3、拼装请求数据
            JDContractSignRequest jdContractSignRequest = new JDContractSignRequest();
            BeanUtils.copyProperties(jdContractSignVo, jdContractSignRequest);
            // 4、调用接口
            JDContractSignDto jdContractSignDto = jdAdpaterService.contractSign(logPrefix, jdContractSignRequest);
            return ResultVO.createSuccess(jdContractSignDto);
        } catch (Exception ex) {
            log.error("{}_error param = {} , {}", logPrefix, JSONUtils.toJSON(jdContractSignVo), ex);
            if(ex instanceof PaymentException) {
                PaymentException paymentException = (PaymentException) ex;
                return ResultVO.createError(paymentException.getErrCode(), paymentException.getErrMsg());
            }
            return ResultVO.createError(ResultCodeEnum.DEFAULT_ERROR);
        } finally {
            if (lockSuc) {
                redisUtil.unLock(lockKey);
            }
        }
    }

    /**
     * 京东 - 协议确认接口
     */
    @Override
    public ResultVO<JDBankCardBindDto> contractSignConfirm(JDContractSignConfirmVo jdContractSignConfirmVo) {
        String logPrefix = "PaymentOpenAccountApiImpl#contractSignConfirm " + jdContractSignConfirmVo.getBusinessReqNo();
        log.info("{} start. JDContractSignConfirmVo:{}", logPrefix, JSONUtils.toJSON(jdContractSignConfirmVo));
        boolean lockSuc = false;
        String lockKey = RedisUtil.getJDContractProc(jdContractSignConfirmVo.getMerchantNo(), jdContractSignConfirmVo.getBindAccount());
        Map<String, String> extent = new HashMap<>();
        String contractReqNo = "";
        BankCardBindLog bankCardBindLog = null;
        try {
            // 1、参数校验
            PojoConvertUtil.checkBlank(jdContractSignConfirmVo, Arrays.asList("merchantNo", "contractNo", "verifyCode", "businessReqNo", "bindAccount", "bindUser", "terminalType", "contractStyle", "businessType", "bankCode", "bankName", "cardType", "cardNo", "idNo", "idName", "phone"));
            if (!redisUtil.tryLock(lockKey)) {
                throw new PaymentException(ResultCodeEnum.JD_BUSY_CONFIRM_SIGN);
            }
            lockSuc = true;
            extent = (null == jdContractSignConfirmVo.getExtent() ? new HashMap<>() : jdContractSignConfirmVo.getExtent());
            extent.put("terminalType", jdContractSignConfirmVo.getTerminalType());
            extent.put("contractStyle", jdContractSignConfirmVo.getContractStyle());
            extent.put("cardNo", jdContractSignConfirmVo.getCardNo());
            extent.put("idNo", jdContractSignConfirmVo.getIdNo());
            // 2、查询签约记录 : merchantNo、bindAccount、bankCode、cardNo：已签约、已解绑、失败
            BankCardBind cardBind = BankCardBind.builder().merchantNo(jdContractSignConfirmVo.getMerchantNo()).bindAccount(jdContractSignConfirmVo.getBindAccount()).bankCode(jdContractSignConfirmVo.getBankCode()).cardNo(jdContractSignConfirmVo.getCardNo()).build();
            BankCardBind existCard = bankCardBindService.queryOne(cardBind, Arrays.asList(JDPayContractStatusEnum.SUCC.getCode(), JDPayContractStatusEnum.REMO.getCode(), JDPayContractStatusEnum.FAIL.getCode()));
            contractReqNo = (null == existCard ? "" : existCard.getContractReqNo());
            // 2.1、若已存在签约成功记录，则抛异常不做处理
            if (null != existCard && JDPayContractStatusEnum.SUCC.getCode() == existCard.getContractStatus()) {
                throw new PaymentException(ResultCodeEnum.JD_CONTRACT_SUCC);
            }
            // 2.2、验证绑卡信息是否与实名信息一致：若身份证号与已成功的不一致，则记录日志，不进行处理
            BankCardBind sucCards = bankCardBindService.queryOne(BankCardBind.builder().merchantNo(jdContractSignConfirmVo.getMerchantNo()).bindAccount(jdContractSignConfirmVo.getBindAccount()).build(), Arrays.asList(JDPayContractStatusEnum.SUCC.getCode(), JDPayContractStatusEnum.REMO.getCode()));
            if (null != sucCards && !jdContractSignConfirmVo.getIdNo().equals(sucCards.getIdNo())) {
                extent.put("oldIdNo", sucCards.getIdNo());
                extent.put("requestIdNo", jdContractSignConfirmVo.getIdNo());
                throw new PaymentException(ResultCodeEnum.JD_CONTRACT_IDNO_ERROR);
            }
            // 3、拼装请求数据
            JDContractSignConfirmRequest jdContractSignConfirmRequest = new JDContractSignConfirmRequest();
            BeanUtils.copyProperties(jdContractSignConfirmVo, jdContractSignConfirmRequest);
            jdContractSignConfirmRequest.setReqNo(leafUtil.getSnowflakeId());
            contractReqNo = (null != existCard ? existCard.getContractReqNo() : jdContractSignConfirmRequest.getReqNo());
            // 4、调用接口查询结果
            JDContractSignConfirmDto jdContractSignConfirmDto = jdAdpaterService.contractSignConfirm(logPrefix, jdContractSignConfirmRequest);
            int status = JDPayContractStatusEnum.transJDPayContractStatus(jdContractSignConfirmDto.getContractStatus());
            if (status != JDPayContractStatusEnum.SUCC.getCode()) {
                throw new Exception(jdContractSignConfirmDto.getResultDesc());
            }
            BankCardBind bankCardBind = BankCardBind.builder()
                    .channel(JDConstants.CHANNEL_CONTRACT).merchantNo(jdContractSignConfirmVo.getMerchantNo())
                    .businessType(jdContractSignConfirmVo.getBusinessType()).reqNo(jdContractSignConfirmRequest.getReqNo())
                    .contractReqNo(contractReqNo).bindAccount(jdContractSignConfirmVo.getBindAccount())
                    .bindUser(jdContractSignConfirmVo.getBindUser()).cardType(jdContractSignConfirmVo.getCardType())
                    .bankCode(jdContractSignConfirmVo.getBankCode()).bankName(jdContractSignConfirmVo.getBankName())
                    .idName(jdContractSignConfirmVo.getIdName()).idType("ID").idNo(jdContractSignConfirmVo.getIdNo())
                    .bankPhone(jdContractSignConfirmVo.getPhone()).extent(JSONObject.toJSONString(extent))
                    .contractStatus(status).contractType(JDPayContractTypeEnum.CONTRACTSIGN.getCode())
                    .contractNo(jdContractSignConfirmVo.getContractNo()).cardNo(jdContractSignConfirmVo.getCardNo())
                    .resultCode(jdContractSignConfirmDto.getResultCode()).resultDesc(jdContractSignConfirmDto.getResultDesc())
                    .build();
            // 5、若已存在签约记录且签约记录不为成功，则失效原记录
            if (null != existCard) {
                existCard.setYn("N");
            }
            // 6、更新结果
            jdAdpaterService.updateResult(existCard, bankCardBind, null);
            // 7、通知商城侧
            jdAdpaterService.notifyShopping(bankCardBind);
            // 8、保存日志记录
            bankCardBindLog = BankCardBindLog.builder().contractReqNo(bankCardBind.getContractReqNo()).contractStatus(status).contractStyle(jdContractSignConfirmVo.getContractStyle()).terminalType(jdContractSignConfirmVo.getTerminalType()).resultCode(jdContractSignConfirmDto.getResultCode()).resultDesc(jdContractSignConfirmDto.getResultDesc()).extent(bankCardBind.getExtent()).build();
            return ResultVO.createSuccess(PojoConvertUtil.convertPojo(bankCardBind, JDBankCardBindDto::new));
        } catch (Exception ex) {
            log.error("{}_error param = {} , {}", logPrefix, JSONUtils.toJSON(jdContractSignConfirmVo), ex);
            bankCardBindLog = BankCardBindLog.builder().contractReqNo(contractReqNo).contractStatus(JDPayContractStatusEnum.FAIL.getCode()).contractStyle(jdContractSignConfirmVo.getContractStyle()).terminalType(jdContractSignConfirmVo.getTerminalType()).resultCode(ResultCodeEnum.DEFAULT_ERROR.getCode()).resultDesc(ex.getMessage()).extent(JSONObject.toJSONString(extent)).build();
            if(ex instanceof PaymentException) {
                PaymentException paymentException = (PaymentException) ex;
                bankCardBindLog.setResultCode(paymentException.getErrCode());
                bankCardBindLog.setResultDesc(paymentException.getErrMsg());
                return ResultVO.createError(paymentException.getErrCode(), paymentException.getErrMsg());
            }
            return ResultVO.createError(ResultCodeEnum.DEFAULT_ERROR);
        } finally {
            if (lockSuc) {
                redisUtil.unLock(lockKey);
            }
            if (StringUtils.isNotBlank(contractReqNo) && null != bankCardBindLog) {
                bankCardBindLogService.insert(bankCardBindLog);
            }
        }
    }

    /**
     * 京东 - 协议解约接口
     */
    @Override
    public ResultVO<JDBankCardBindDto> cancelContract(JDCancelContractVo jdCancelContractVo) {
        String logPrefix = "PaymentOpenAccountApiImpl#cancelContract " + jdCancelContractVo.getBusinessReqNo();
        log.info("{} start. JDCancelContractVo:{}", logPrefix, JSONUtils.toJSON(jdCancelContractVo));
        boolean lockSuc = false;
        String lockKey = RedisUtil.JD_PAY_PREFIX + "cancelContract_" + jdCancelContractVo.getReqNo();
        try {
            // 1.参数校验
            PojoConvertUtil.checkBlank(jdCancelContractVo, Arrays.asList("terminalType", "contractStyle", "businessType", "businessReqNo", "reqNo"));
            if (!redisUtil.tryLock(lockKey)) {
                throw new PaymentException(ResultCodeEnum.JD_BUSY_CONTRACT_CANCEL);
            }
            lockSuc = true;
            // 2、查询绑卡数据
            BankCardBind queryOne = bankCardBindService.queryOne(BankCardBind.builder().reqNo(jdCancelContractVo.getReqNo()).build());
            if (null == queryOne) {
                throw new PaymentException(ResultCodeEnum.JD_CONTRACT_NOTEXIST);
            }
            // 3、拼装请求数据
            JDCancelContractRequest jdCancelContractRequest = JDCancelContractRequest.builder().reqNo(queryOne.getReqNo()).merchantNo(queryOne.getMerchantNo()).contractNo(queryOne.getContractNo()).build();
            // 4、调用接口 (无论解约是否成功，均按解约成功处理)
            JDCancelContractDto jdCancelContractDto = jdAdpaterService.cancelContract(logPrefix, jdCancelContractRequest);
            // 5、更新结果
            queryOne.setContractStatus(JDPayContractStatusEnum.REMO.getCode());
            bankCardBindService.update(queryOne);
            // 6、保存记录
            BankCardBindLog bankCardBindLog = BankCardBindLog.builder().contractReqNo(queryOne.getContractReqNo()).contractStatus(JDPayContractStatusEnum.REMO.getCode()).contractStyle(jdCancelContractVo.getContractStyle())
                    .terminalType(jdCancelContractVo.getTerminalType()).resultCode(jdCancelContractDto.getResultCode()).resultDesc(jdCancelContractDto.getResultDesc())
                    .extent(null == jdCancelContractVo.getExtent() ? "" : JSONObject.toJSONString(jdCancelContractVo.getExtent())).build();
            bankCardBindLogService.insert(bankCardBindLog);
            return ResultVO.createSuccess(PojoConvertUtil.convertPojo(queryOne, JDBankCardBindDto::new));
        } catch (Exception ex) {
            log.error("{}_error param = {} , {}", logPrefix, JSONUtils.toJSON(jdCancelContractVo), ex);
            if(ex instanceof PaymentException) {
                PaymentException paymentException = (PaymentException) ex;
                return ResultVO.createError(paymentException.getErrCode(), paymentException.getErrMsg());
            }
            return ResultVO.createError(ResultCodeEnum.DEFAULT_ERROR);
        } finally {
            if (lockSuc) {
                redisUtil.unLock(lockKey);
            }
        }
    }

    /**
     * 京东 - 查询客户绑卡列表
     */
    @Override
    public ResultVO<List<JDBankCardBindDto>> bindCardList(JDBankCardBindVo jdBankCardBindVo) {
        String logPrefix = "PaymentOpenAccountApiImpl#bindCardList " + jdBankCardBindVo.getBindAccount();
        log.info("{} start. JDCancelContractVo:{}", logPrefix, JSONUtils.toJSON(jdBankCardBindVo));
        try {
            // 1、参数校验
            PojoConvertUtil.checkBlank(jdBankCardBindVo, Arrays.asList("merchantNo", "bindAccount"));
            // 2、查询数据 : merchantNo、bindAccount、contractStatus
            BankCardBind bankCardBind = BankCardBind.builder().merchantNo(jdBankCardBindVo.getMerchantNo()).bindAccount(jdBankCardBindVo.getBindAccount()).contractStatus(JDPayContractStatusEnum.SUCC.getCode()).build();
            List<BankCardBind> cardBinds = bankCardBindService.appCardList(bankCardBind);
            // 3、对数据做转换并返回
            return ResultVO.createSuccess(PojoConvertUtil.copyList(cardBinds, JDBankCardBindDto::new));
        } catch (Exception ex) {
            log.error("{}_error param = {} , {}", logPrefix, JSONUtils.toJSON(jdBankCardBindVo), ex);
            if(ex instanceof PaymentException) {
                PaymentException paymentException = (PaymentException) ex;
                return ResultVO.createError(paymentException.getErrCode(), paymentException.getErrMsg());
            }
            return ResultVO.createError(ResultCodeEnum.DEFAULT_ERROR);
        }
    }

    @Override
    public ResultVO clearBindCards(String merchantNo, String bindAccount) {
        String logPrefix = "jdpay_clearMerchant_" + bindAccount;
        // 参数校验
        if (StringUtils.isBlank(merchantNo) || StringUtils.isBlank(bindAccount)) {
            return ResultVO.createError(ResultCodeEnum.PARAM_ERROR.getCode(), ResultCodeEnum.PARAM_ERROR.getDisplayMsg());
        }
        BankCardBind cardBind = BankCardBind.builder().merchantNo(merchantNo).bindAccount(bindAccount).build();
        List<BankCardBind> bankCardBinds = bankCardBindService.appCardList(cardBind);
        if (CollectionUtils.isEmpty(bankCardBinds)) {
            log.info("{} 无签约数据，不进行处理 {}", logPrefix, JSONObject.toJSONString(cardBind));
            return ResultVO.createSuccess();
        }
        for (BankCardBind bankCardBind : bankCardBinds) {
            log.info("{} 开始处理 {} ", logPrefix, JSONObject.toJSONString(bankCardBind));
            if (JDPayContractStatusEnum.SUCC.getCode() == bankCardBind.getContractStatus()) {
                jdAdpaterService.cancelContract(logPrefix, JDCancelContractRequest.builder().merchantNo(bankCardBind.getMerchantNo()).contractNo(bankCardBind.getContractNo()).reqNo(bankCardBind.getReqNo()).build());
                bankCardBind.setContractStatus(JDPayContractStatusEnum.REMO.getCode());
            }
            bankCardBind.setYn("N");
            log.info("{} 更新签约信息 {}", logPrefix, JSONObject.toJSONString(bankCardBind));
            bankCardBindService.update(bankCardBind);
        }
        return ResultVO.createSuccess();
    }
    @Override
    public ResultVO clearBindCards(JDBankCardBindVo param) {
        String logPrefix = "jdpay_clearMerchant_" + JSONUtils.toJSON(param.getBindAccountList());
        // 参数校验
        if (StringUtils.isBlank(param.getMerchantNo()) || CollectionUtils.isEmpty(param.getBindAccountList())) {
            return ResultVO.createError(ResultCodeEnum.PARAM_ERROR.getCode(), ResultCodeEnum.PARAM_ERROR.getDisplayMsg());
        }
        BankCardBind cardBind = BankCardBind.builder().merchantNo(param.getMerchantNo()).bindAccountList(param.getBindAccountList()).build();
        List<BankCardBind> bankCardBinds = bankCardBindService.appCardList(cardBind);
        if (CollectionUtils.isEmpty(bankCardBinds)) {
            log.info("{} 无签约数据，不进行处理 {}", logPrefix, JSONObject.toJSONString(cardBind));
            return ResultVO.createSuccess();
        }
        for (BankCardBind bankCardBind : bankCardBinds) {
            log.info("{} 开始处理 {} ", logPrefix, JSONObject.toJSONString(bankCardBind));
            if (JDPayContractStatusEnum.SUCC.getCode() == bankCardBind.getContractStatus()) {
                jdAdpaterService.cancelContract(logPrefix, JDCancelContractRequest.builder().merchantNo(bankCardBind.getMerchantNo()).contractNo(bankCardBind.getContractNo()).reqNo(bankCardBind.getReqNo()).build());
                bankCardBind.setContractStatus(JDPayContractStatusEnum.REMO.getCode());
            }
            bankCardBind.setYn("N");
            log.info("{} 更新签约信息 {}", logPrefix, JSONObject.toJSONString(bankCardBind));
            bankCardBindService.update(bankCardBind);
        }
        return ResultVO.createSuccess();
    }
}
